package com.cryptoneedle.center.doris.repository.metadata;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.cryptoneedle.center.common.constants.CommonConstant;
import com.cryptoneedle.center.doris.domain.metadata.DorisMetadataCatalog;
import com.cryptoneedle.center.doris.domain.metadata.DorisMetadataDatabase;
import com.cryptoneedle.center.doris.domain.metadata.DorisMetadataTable;
import com.cryptoneedle.center.doris.domain.metadata.DorisMetadataTableStatus;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>description: Doris-元数据 </p>
 * <p>
 * 由于 Jpa 和 JdbcTemplate 限制，使用原生 Jdbc Api 调用 Doris 语句
 *
 * @author CryptoNeedle
 * @date 2025-09-25
 */
@Service
@Slf4j
@Transactional(propagation = Propagation.REQUIRES_NEW)
@DS("doris")
public class DorisMetadataRepository {

    @Resource
    private JdbcTemplate jdbcTemplate;

    public List<DorisMetadataCatalog> showCatalogs() {
        List<DorisMetadataCatalog> list = new ArrayList<>();

        String sql = "SHOW CATALOGS";
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.prepareStatement(sql).executeQuery(sql);
            while (rs.next()) {
                DorisMetadataCatalog domain = new DorisMetadataCatalog();
                domain.setCatalogId(rs.getLong("CatalogId"));
                domain.setCatalogName(rs.getString("CatalogName"));
                domain.setType(rs.getString("Type"));
                domain.setIsCurrent(rs.getString("IsCurrent"));
                domain.setCreateTime(rs.getString("CreateTime"));
                domain.setLastUpdateTime(rs.getString("LastUpdateTime"));
                domain.setComment(rs.getString("Comment"));

                list.add(domain);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return list;
    }

    public List<DorisMetadataDatabase> showDatabases() {
        List<DorisMetadataDatabase> list = new ArrayList<>();

        String sql = "SHOW DATABASES";
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.prepareStatement(sql).executeQuery(sql);
            while (rs.next()) {
                DorisMetadataDatabase domain = new DorisMetadataDatabase();
                domain.setCatalogName(rs.getString(CommonConstant.DORIS_CATALOG));
                domain.setDatabaseName(rs.getString("Database"));

                list.add(domain);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return list;
    }

    public List<DorisMetadataDatabase> showDatabasesFrom(String catalogName) {
        List<DorisMetadataDatabase> list = new ArrayList<>();

        String sql = "SHOW DATABASES FROM %s".formatted(catalogName);
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.prepareStatement(sql).executeQuery();
            while (rs.next()) {
                DorisMetadataDatabase domain = new DorisMetadataDatabase();
                domain.setCatalogName(catalogName);
                domain.setDatabaseName(rs.getString("Database"));

                list.add(domain);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return list;
    }

    public List<DorisMetadataTable> showFullTablesFrom(String catalogName, String databaseName) {
        List<DorisMetadataTable> list = new ArrayList<>();

        String sql = "SHOW FULL TABLES FROM %s.%s".formatted(catalogName, databaseName);
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.prepareStatement(sql).executeQuery();
            while (rs.next()) {
                DorisMetadataTable domain = new DorisMetadataTable();
                domain.setCatalogName(catalogName);
                domain.setDatabaseName(databaseName);
                domain.setTableName(rs.getString("Tables_in_" + databaseName));
                domain.setTableType(rs.getString("Table_type"));
                domain.setStorageFormat(rs.getString("Storage_format"));
                domain.setInvertedIndexStorageFormat(rs.getString("Inverted_index_storage_format"));

                list.add(domain);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return list;
    }

    public List<DorisMetadataTableStatus> showTableStatusFrom(String catalogName, String databaseName) {
        List<DorisMetadataTableStatus> list = new ArrayList<>();

        String sql = "SHOW TABLE STATUS FROM %s.%s".formatted(catalogName, databaseName);
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.prepareStatement(sql).executeQuery();
            while (rs.next()) {
                DorisMetadataTableStatus domain = new DorisMetadataTableStatus();
                domain.setCatalogName(catalogName);
                domain.setDatabaseName(databaseName);
                domain.setTableName(rs.getString("Name"));
                domain.setEngine(rs.getString("Engine"));
                domain.setTableRows(rs.getLong("Rows"));
                domain.setAvgRowLength(rs.getLong("Avg_row_length"));
                domain.setDataLength(rs.getLong("Data_length"));
                domain.setCreateTime(rs.getDate("Create_time"));
                domain.setUpdateTime(rs.getDate("Update_time"));
                domain.setTableCollation(rs.getString("Collation"));
                domain.setTableComment(rs.getString("Comment"));

                list.add(domain);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return list;
    }

    public DorisMetadataTableStatus showTableStatusFromWhere(String catalogName, String databaseName, String tableName) {
        DorisMetadataTableStatus domain = null;

        String sql = "SHOW TABLE STATUS FROM %s.%s WHERE Name = '%s'".formatted(catalogName, databaseName, tableName);
        try (Connection connection = jdbcTemplate.getDataSource().getConnection()) {
            ResultSet rs = connection.prepareStatement(sql).executeQuery();
            while (rs.next()) {
                domain = new DorisMetadataTableStatus();
                domain.setCatalogName(catalogName);
                domain.setDatabaseName(databaseName);
                domain.setTableName(rs.getString("Name"));
                domain.setEngine(rs.getString("Engine"));
                domain.setTableRows(rs.getLong("Rows"));
                domain.setAvgRowLength(rs.getLong("Avg_row_length"));
                domain.setDataLength(rs.getLong("Data_length"));
                domain.setCreateTime(rs.getDate("Create_time"));
                domain.setUpdateTime(rs.getDate("Update_time"));
                domain.setTableCollation(rs.getString("Collation"));
                domain.setTableComment(rs.getString("Comment"));
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }

        return domain;
    }
}